package main

import (
	"database/sql"
	"fmt"
	_ "github.com/go-sql-driver/mysql"
	"log"
)

type options struct {
	optionId    int
	optionName  string
	optionValue string
	autoload    string
}

// 多行
func queryDemo(db *sql.DB) {
	// 1.sql 语句
	sqlStr := `select * from wp_options where option_id > ?;`
	// 2.查询
	rows, err := db.Query(sqlStr, 1)
	if err != nil {
		fmt.Println(err)
		return
	}
	// 3.defer 关闭rows
	defer rows.Close()
	// 4. 循环取值
	for rows.Next() {
		var o options
		if err = rows.Scan(&o.optionId, &o.optionName, &o.optionValue, &o.autoload); err != nil {
			fmt.Println(err)
		}
		fmt.Printf("%#v\n", o)
	}
}

// 单行查询
func queryRowDemo(db *sql.DB) {
	var o options
	defer db.Close()
	sqlStr := `select * from wp_options where option_id=?;`
	err := db.QueryRow(sqlStr, 2).Scan(&o.optionId, &o.optionName, &o.optionValue, &o.autoload)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Printf("%#v\n", o)
}

// 插入
func insertDemo(db *sql.DB) {
	// 1.sql语句
	sqlStr := `insert into wp_options(option_name,option_value) values("mingof_test","test")`
	// 2.exec
	var ret sql.Result
	var err error
	if ret, err = db.Exec(sqlStr); err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(ret.LastInsertId())
}

// 更新
func updateDemo(db *sql.DB) {
	// 1.sql语句
	sqlStr := `update wp_options set option_name=? where option_name='mingof_test'`
	// 2.exec
	var ret sql.Result
	var err error
	if ret, err = db.Exec(sqlStr, "haha2"); err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(ret.RowsAffected())
}

// 删除
func deleteDemo(db *sql.DB) {
	// 1.sql语句
	sqlStr := `delete from wp_options where option_name=?`
	// 2.exec
	var ret sql.Result
	var err error
	if ret, err = db.Exec(sqlStr, "haha"); err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(ret.RowsAffected())
}

func initDB(dsn string) (*sql.DB, error) {
	// 数据库信息 ssh 格式
	//链接数据库
	db, err := sql.Open("mysql", dsn)
	if err != nil {
		log.Println("failed connect", dsn, err)
		return nil, err
	}
	if err = db.Ping(); err != nil {
		fmt.Println(err)
		return nil, err
	}
	fmt.Println("数据库连接成功")
	// 设置数据库连接池的最大连接数据
	db.SetMaxOpenConns(10)
	// 设置最大空闲连接数
	db.SetMaxIdleConns(5)
	return db, nil
}

// mysql预处理
func preparedQueryDemo(db *sql.DB) {
	var (
		stmt *sql.Stmt
		err  error
		row  *sql.Row
		o    options
	)
	sqlStr := `select * from wp_options where option_id=?;`
	if stmt, err = db.Prepare(sqlStr); err != nil {
		fmt.Println(err)
		return
	}
	defer stmt.Close()
	for i := 0; i < 100; i++ {
		if row = stmt.QueryRow(i); row.Err() != nil {
			fmt.Println(row.Err())
			continue
		}
		err = row.Scan(&o.optionId, &o.optionName, &o.optionValue, &o.autoload)
		if err != nil {
			fmt.Println(err)
			continue
		}
		fmt.Println(o)
	}
}

// 事务
func transactionDemo(db *sql.DB) {
	// 开启事务
	tx, err := db.Begin()
	if err != nil {
		fmt.Println(err)
		return
	}
	// 多个sql语句
	sqlStr1 := `insert into wp_options(option_name,option_value) values("mingof_test","test")`
	sqlStr2 := `update wp_options set option_value="mingof_test" where option_name="mingof_test"`
	// 执行多个sql语句
	if _, err = tx.Exec(sqlStr1); err != nil {
		fmt.Println(err)
		tx.Rollback()
		return
	}
	if _, err = tx.Exec(sqlStr2); err != nil {
		fmt.Println(err)
		tx.Rollback()
		return
	}
	// 如果sql都执行成功，就执行Commit
	if err = tx.Commit(); err != nil {
		fmt.Println(err)
		tx.Rollback()
		return
	}
}
func main() {
	dsn := "wordpress:wordpress@tcp(127.0.0.1:3306)/wordpress"
	db, err := initDB(dsn) // db是一个连接池
	if err != nil {
		fmt.Println(err)
		return
	}
	//queryRowDemo(db)
	//queryDemo(db)
	//insertDemo(db)
	//updateDemo(db)
	//deleteDemo(db)
	//preparedQueryDemo(db)
	transactionDemo(db)
}
